package com.spontaneappnew.activities;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import com.facebook.Request;
import com.facebook.Response;
import com.facebook.Session;
import com.facebook.model.GraphUser;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.parse.Parse;
import com.spontaneappnew.Categories;
import com.spontaneappnew.Places;
import com.spontaneappnew.R;

public class SplashScreenActivity extends FragmentActivity 
										implements AnimationListener, GooglePlayServicesClient.ConnectionCallbacks,
														GooglePlayServicesClient.OnConnectionFailedListener, LocationListener{

	protected boolean isLocationServicesAvailable = false;
	
	private LocationClient mLocationClient;
	// Global variable to hold the current location
    private Location mCurrentLocation;
    // Define an object that holds accuracy, frequency and number of updates parameters
    private LocationRequest mLocationRequest;
    
    private SharedPreferences pref;
    private SharedPreferences.Editor editor;
    
    private Bundle locationBundle;
	
	/*
     * Define a request code to send to Google Play services to check whether Google Play services(location)
     * are available on the user's device.
     * This code is returned in Activity.onActivityResult() method
     */
    private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
	// Default value for checking if location services are available
    private final static int LOCATION_MODE_OFF_AS_DEFAULT = 0;
    private final static int FROM_SETTINGS_REQUEST_CODE = 9001;
    
    // Animation
    Animation animMoveToMiddle;
    Animation animMoveToTop;
    ImageView appIcon;
    
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_splash_screen);
		
		// User came from notification when he left a place, so we show the RateAndComment activity
		if (getIntent().hasExtra("startRateActivity")) {
		    Intent intent = new Intent(this, RateAndCommentPlaceActivity.class);
		    String placeId = getIntent().getStringExtra("placeId");
		    String placeName = getIntent().getStringExtra("placeName");
		    intent.putExtra("placeId", placeId);
		    intent.putExtra("placeName", placeName);
		    startActivity(intent);
		    // finish this activity
		    finish();
		    // Return here so we don't execute the rest of onCreate()
		    return;
		}
		
		locationBundle = null;
		
		pref = getSharedPreferences("PREF", MODE_PRIVATE);
		editor = pref.edit();
				
		// No need for the actionbar on the loading screen
		getActionBar().hide();
		
		// load the animation
        animMoveToMiddle = AnimationUtils.loadAnimation(getApplicationContext(),
                R.anim.move_from_buttom_to_middle);
        animMoveToTop = AnimationUtils.loadAnimation(getApplicationContext(),
        		R.anim.move_from_middle_to_top);
        animMoveToTop.setAnimationListener(this);
		appIcon = (ImageView) findViewById(R.id.splash_app_icon);
		appIcon.startAnimation(animMoveToMiddle);
        
		/*
         * Create a new location client, using the enclosing class to
         * handle callbacks.
         */
        mLocationClient = new LocationClient(this, this, this);
        
        mLocationRequest = LocationRequest.create();
        // Use high accuracy
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        // Set the request for only one update
        mLocationRequest.setNumUpdates(1);
		
	}

	private class InitializeAppData extends AsyncTask<Void, Void, Void>{
		
		@Override
		protected Void doInBackground(Void... params) {
			int radius = pref.getInt("radius", 10);
			// if radius is in miles, convert it to km
			if(!pref.getBoolean("isKm", true))
				radius *= 1.6;
			Parse.initialize(SplashScreenActivity.this, "OHKt17cGZqBhJEdOcHDQW771ZhUQgTrkd3IAWrRk", "IckQgfToDOtil3LEf586QW3bDLeAVa7PE8SWaxU6");
	        // Get the categories singleton
	        Categories.getInstance();
	        Places.getInitializedInstance(mCurrentLocation,radius);
	        String FBID = pref.getString("FBID", "");
	        if(FBID.compareTo("") == 0){
		    	Session session = Session.getActiveSession();
		    	// We just came from login screen so we have to have a session open!
		        if (session != null && session.isOpened()){
		        	makeMeRequest(session);
		        }
		        FBID = pref.getString("FBID", "");
	        }
        	Places.getInstance().startGettingFromServer(FBID);
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);
			appIcon.startAnimation(animMoveToTop);
		}
		
	}
	
	@Override
	protected void onResume(){
		super.onResume();
		// Check if location services are available. 
	   // If not, show a dialog that alerts the user and takes him to the settings menu to change it.
	   isLocationServicesAvailable();

        // Check if the Google Play Services and location services are available, if not a dialog pops up 
 		if(servicesConnected() && isLocationServicesAvailable){
	 		if(!mLocationClient.isConnected()){
 				// Connect the client.
	 	        mLocationClient.connect();
	 		}
 		}
	}
	
	@Override
	protected void onPause() {
		// If the client is connected
        if (mLocationClient.isConnected()) 
            // Remove location updates for a listener.
            // The current Activity is the listener, so the argument is "this".
        	mLocationClient.removeLocationUpdates(this);
		// Disconnecting the client invalidates it.
        mLocationClient.disconnect();
		super.onPause();
		// if came from notification no need to add activity to stack
		if(getIntent().hasExtra("startRateActivity"))
			finish();
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
			case FROM_SETTINGS_REQUEST_CODE:
				onResume();
			break;
			case CONNECTION_FAILURE_RESOLUTION_REQUEST :
				/*
	             * If the result code is Activity.RESULT_OK, try
	             * to connect again
	             */
	                switch (resultCode) {
	                    case Activity.RESULT_OK :
	                    //Try the request again
	                    servicesConnected();
	                    break;
	                }
			break;
			default:
			break;
        }
	}
	
	/*
	 * Creates request to get the user's id
	 */
	private void makeMeRequest(final Session session) {
	    // Make an API call to get user data and define a 
	    // new callback to handle the response.
	    Request request = Request.newMeRequest(session, 
	            new Request.GraphUserCallback() {
	        @Override
	        public void onCompleted(GraphUser user, Response response) {
	            // If the response is successful
	            if (session == Session.getActiveSession()) {
	                if (user != null) {
	                	// Save the user's FB id in SharedPreferences
	                	String FBID = pref.getString("FBID", "");
	                	if(FBID.compareTo("") == 0){
	                		editor.putString("FBID", user.getId());
	                		editor.commit();
	                	}
	                }
	            }
	        }
	    });
	    request.executeAndWait();
	} 
	
	 ///////////////////// Google Play Services and Location Services (location uses) ///////////////////////////////
	
	/*
	 * Checks if the Google Play services are available, return true/false accordingly
	 * If the services are not available show a dialog helping the user to get it to work
	 * Through sending him to enable it or to the Play store
	 */
	protected boolean servicesConnected() {
       // Check that Google Play services is available
       int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
       // If Google Play services is available
       if (ConnectionResult.SUCCESS == resultCode) {
           // Continue
           return true;
       // Google Play services was not available for some reason
       } else {
       	int errorCode = resultCode;
           // Get the error dialog from Google Play services
           Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
                   errorCode, this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
           // If Google Play services can provide an error dialog
           if (errorDialog != null) {
               // Create a new DialogFragment for the error dialog
               ErrorDialogFragment errorFragment =
                       new ErrorDialogFragment();
               // Set the dialog in the DialogFragment
               errorFragment.setDialog(errorDialog);
               // Show the error dialog in the DialogFragment
               errorFragment.show(getSupportFragmentManager(),
                       "Location Updates");
           }
           return false;
       }
   }
	
	// Define a DialogFragment that displays the error dialog
   public static class ErrorDialogFragment extends DialogFragment {
       // Global field to contain the error dialog
       private Dialog mDialog;
       // Default constructor. Sets the dialog field to null
       public ErrorDialogFragment() {
           super();
           mDialog = null;
       }
       // Set the dialog to display
       public void setDialog(Dialog dialog) {
           mDialog = dialog;
       }
       // Return a Dialog to the DialogFragment.
       @Override
       public Dialog onCreateDialog(Bundle savedInstanceState) {
           return mDialog;
       }
   }
   
   @Override
	public void onConnected(Bundle bundle) {
	   mCurrentLocation = mLocationClient.getLastLocation();
	   if(mCurrentLocation == null){
		   // Default values in case of an error
		   mCurrentLocation = new Location("DEFAULT");
		   mCurrentLocation.setLatitude(31.264479);
		   mCurrentLocation.setLongitude(34.80285);
		 // if current location is not null put the location in a bundle and put it in the intent for homeActivity to use to calc distance better
	   }else{
		   locationBundle = new Bundle();
		   locationBundle.putDouble("lat", mCurrentLocation.getLatitude());
		   locationBundle.putDouble("lng", mCurrentLocation.getLongitude());
	   }
	   // Make an update request for one accurate current location
	   mLocationClient.requestLocationUpdates(mLocationRequest, this);
	   
	   /* Call function that takes current location in lat and lng and wanted distance and updates 
	    * the minMaxLatLngValues array with minimum and maximum lat and lng values of the 
	    * area we need to get all places from.
	    */
	  
	   // after calculating the wanted area start initializing the app's data and get places and categories from the server
	   new InitializeAppData().execute();
   }
   
   /*minimum long minimum lat max long max lat radius
    * Gets current location in lat/lng and the wanted radius, calculates the rounded min/max lat/lng
    * values in the range and puts them in an array for later use to filter places more efficiently.
    */
 
	@Override
	public void onDisconnected() {}
   
   /*
    * Called by Location Services if the attempt to
    * Location Services fails.
    */
   @Override
   public void onConnectionFailed(ConnectionResult connectionResult) {
       /*
        * Google Play services can resolve some errors it detects.
        * If the error has a resolution, try sending an Intent to
        * start a Google Play services activity that can resolve
        * error.
        */
       if (connectionResult.hasResolution()) {
           try {
               // Start an Activity that tries to resolve the error
               connectionResult.startResolutionForResult(
                       this,
                       CONNECTION_FAILURE_RESOLUTION_REQUEST);
               /*
                * Thrown if Google Play services canceled the original
                * PendingIntent
                */
           } catch (IntentSender.SendIntentException e) {
               // Log the error
               e.printStackTrace();
           }
       } else {
           /*
            * If no resolution is available, display a dialog to the
            * user with the error.
            */
           showErrorDialog(connectionResult.getErrorCode());
       }
   }
   
   /*
    * Gets an error code and show an AlertDialog accordingly.
    * Helper function for the location services from Google Play services when trying to connect
    * and recieve an error
    */
   protected void showErrorDialog(int errorCode) {
       new AlertDialog.Builder(this)
               .setMessage(String.valueOf(errorCode))
               .setPositiveButton(android.R.string.ok,
                       new DialogInterface.OnClickListener() {
                           public void onClick(DialogInterface dialog, int id) {
                               dialog.dismiss();
                           }
                       }).show();
   }
   
    /*
     * Check if location services are available. 
     * If not, show a dialog that alerts the user and takes him to the settings menu to change it.
     */
   @SuppressLint("InlinedApi")
	protected void isLocationServicesAvailable(){
   	// Checks the user's API - if >= KITKAT, use 'LOCATION_MODE', else use 'LOCATION_PROVIDERS_ALLOWED'
   	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
	    	int locationProviders = Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE, LOCATION_MODE_OFF_AS_DEFAULT);
	    	switch (locationProviders) {
	    	case Settings.Secure.LOCATION_MODE_OFF:
	    		showLocationServicesOffDialog();
	    		break;
	    	default:
	    		isLocationServicesAvailable = true;
	    		break;
	    	}
   	}
   	// User has API < KITKAT(19)
   	else{
   		@SuppressWarnings("deprecation")
			String locationProviders = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
   		if (locationProviders == null || locationProviders.equals("")) {
   			showLocationServicesOffDialog();
   		}
   		else{
   			isLocationServicesAvailable = true;
   		}
   	}
   }
   
   /* Shows a dialog to alert the user that his location services are disabled and take him to the settings
    * if he wants to.
    */ 
   private void showLocationServicesOffDialog(){
   	String title = "Location services disabled";
   	String msg = "SpontaneApp needs access to your location.\nPlease turn on location access.";
   	AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(msg)
				.setTitle(title)
				.setCancelable(false)
				.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
		        	public void onClick(DialogInterface dialog, int id) {
		        	   // Go to phone's Location settings screen
		        		dialog.dismiss();
		        	   startActivityForResult(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS), FROM_SETTINGS_REQUEST_CODE);
		        	}
				});
//				.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
//		        	public void onClick(DialogInterface dialog, int id) {
//		        	    // Dismiss dialog and state of boolean field to false
//		        		isLocationServicesAvailable = false;
//		        		dialog.dismiss();
//		        	}
//				});
		AlertDialog alert = builder.create();
		alert.show();
   }

	@Override
	public void onLocationChanged(Location newLocation) {
		mCurrentLocation = newLocation;
	}

////////////////////////////// ANIMATION ///////////////////////////////////////////////////
	
	@Override
	public void onAnimationEnd(Animation animation) {
		if(animation == animMoveToTop){
			Intent intent = new Intent(SplashScreenActivity.this, HomeActivity.class);
			if(locationBundle != null){
				intent.putExtras(locationBundle);
			}
			startActivity(intent);
			finish();
		}
	}

	@Override
	public void onAnimationRepeat(Animation animation) {
		
	}

	@Override
	public void onAnimationStart(Animation animation) {
		
	}

}
